<template><div><h2 id="格式化响应" tabindex="-1"><a class="header-anchor" href="#格式化响应"><span>格式化响应</span></a></h2>
<p>When handling a RESTful API request, an application usually takes the following steps that are related with response formatting:</p>
<ol>
<li>Determine various factors that may affect the response format, such as media type, language, version, etc. This process is also known as <a href="https://en.wikipedia.org/wiki/Content_negotiation" target="_blank" rel="noopener noreferrer">content negotiation</a>.</li>
<li>Convert resource objects into arrays, as described in the <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide/rest-resources.md" target="_blank" rel="noopener noreferrer">Resources</a> section. This is done by [[yii\rest\Serializer]].</li>
<li>Convert arrays into a string in the format as determined by the content negotiation step. This is done by [[yii\web\ResponseFormatterInterface|response formatters]] registered with the [[yii\web\Response::formatters|formatters]] property of the <code v-pre>response</code> <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide/structure-application-components.md" target="_blank" rel="noopener noreferrer">application component</a>.</li>
</ol>
<h2 id="content-约定" tabindex="-1"><a class="header-anchor" href="#content-约定"><span>Content 约定</span></a></h2>
<p>Yii supports content negotiation via the [[yii\filters\ContentNegotiator]] filter. The RESTful API base controller class [[yii\rest\Controller]] is equipped with this filter under the name of <code v-pre>contentNegotiator</code>. The filter provides response format negotiation as well as language negotiation. For example, if a RESTful API request contains the following header,</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">Accept<span class="token punctuation">:</span> application<span class="token operator">/</span>json<span class="token punctuation">;</span> q<span class="token operator">=</span><span class="token number">1.0</span><span class="token punctuation">,</span> <span class="token operator">*</span><span class="token operator">/</span><span class="token operator">*</span><span class="token punctuation">;</span> q<span class="token operator">=</span><span class="token number">0.1</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>it will get a response in JSON format, like the following:</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">$ <span class="token function">curl</span> <span class="token parameter variable">-i</span> <span class="token parameter variable">-H</span> <span class="token string">"Accept: application/json; q=1.0, */*; q=0.1"</span> <span class="token string">"http://localhost/users"</span></span>
<span class="line"></span>
<span class="line">HTTP/1.1 <span class="token number">200</span> OK</span>
<span class="line">Date: Sun, 02 Mar <span class="token number">2014</span> 05:31:43 GMT</span>
<span class="line">Server: Apache/2.2.26 <span class="token punctuation">(</span>Unix<span class="token punctuation">)</span> DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y</span>
<span class="line">X-Powered-By: PHP/5.4.20</span>
<span class="line">X-Pagination-Total-Count: <span class="token number">1000</span></span>
<span class="line">X-Pagination-Page-Count: <span class="token number">50</span></span>
<span class="line">X-Pagination-Current-Page: <span class="token number">1</span></span>
<span class="line">X-Pagination-Per-Page: <span class="token number">20</span></span>
<span class="line">Link: <span class="token operator">&lt;</span>http://localhost/users?page<span class="token operator">=</span><span class="token operator"><span class="token file-descriptor important">1</span>></span><span class="token punctuation">;</span> <span class="token assign-left variable">rel</span><span class="token operator">=</span>self,</span>
<span class="line">      <span class="token operator">&lt;</span>http://localhost/users?page<span class="token operator">=</span><span class="token operator"><span class="token file-descriptor important">2</span>></span><span class="token punctuation">;</span> <span class="token assign-left variable">rel</span><span class="token operator">=</span>next,</span>
<span class="line">      <span class="token operator">&lt;</span>http://localhost/users?page<span class="token operator">=</span><span class="token number">5</span><span class="token operator"><span class="token file-descriptor important">0</span>></span><span class="token punctuation">;</span> <span class="token assign-left variable">rel</span><span class="token operator">=</span>last</span>
<span class="line">Transfer-Encoding: chunked</span>
<span class="line">Content-Type: application/json<span class="token punctuation">;</span> <span class="token assign-left variable">charset</span><span class="token operator">=</span>UTF-8</span>
<span class="line"></span>
<span class="line"><span class="token punctuation">[</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token string">"id"</span><span class="token builtin class-name">:</span> <span class="token number">1</span>,</span>
<span class="line">        <span class="token punctuation">..</span>.</span>
<span class="line">    <span class="token punctuation">}</span>,</span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token string">"id"</span><span class="token builtin class-name">:</span> <span class="token number">2</span>,</span>
<span class="line">        <span class="token punctuation">..</span>.</span>
<span class="line">    <span class="token punctuation">}</span>,</span>
<span class="line">    <span class="token punctuation">..</span>.</span>
<span class="line"><span class="token punctuation">]</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Behind the scene, before a RESTful API controller action is executed, the [[yii\filters\ContentNegotiator]] filter will check the <code v-pre>Accept</code> HTTP header in the request and set the [[yii\web\Response::format|response format]] to be <code v-pre>'json'</code>. After the action is executed and returns the resulting resource object or collection, [[yii\rest\Serializer]] will convert the result into an array. And finally, [[yii\web\JsonResponseFormatter]] will serialize the array into a JSON string and include it in the response body.</p>
<p>By default, RESTful APIs support both JSON and XML formats. To support a new format, you should configure the [[yii\filters\ContentNegotiator::formats|formats]] property of the <code v-pre>contentNegotiator</code> filter like the following in your API controller classes:</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>web<span class="token punctuation">\</span>Response</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">behaviors</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$behaviors</span> <span class="token operator">=</span> <span class="token keyword static-context">parent</span><span class="token operator">::</span><span class="token function">behaviors</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token variable">$behaviors</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'contentNegotiator'</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'formats'</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'text/html'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token class-name static-context">Response</span><span class="token operator">::</span><span class="token constant">FORMAT_HTML</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token variable">$behaviors</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The keys of the <code v-pre>formats</code> property are the supported MIME types, while the values are the corresponding response format names which must be supported in [[yii\web\Response::formatters]].</p>
<h2 id="数据序列化" tabindex="-1"><a class="header-anchor" href="#数据序列化"><span>数据序列化</span></a></h2>
<p>As we have described above, [[yii\rest\Serializer]] is the central piece responsible for converting resource objects or collections into arrays. It recognizes objects implementing [[yii\base\Arrayable]] as well as [[yii\data\DataProviderInterface]]. The former is mainly implemented by resource objects, while the latter resource collections.</p>
<p>You may configure the serializer by setting the [[yii\rest\Controller::serializer]] property with a configuration array. For example, sometimes you may want to help simplify the client development work by including pagination information directly in the response body. To do so, configure the [[yii\rest\Serializer::collectionEnvelope]] property as follows:</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>rest<span class="token punctuation">\</span>ActiveController</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">UserController</span> <span class="token keyword">extends</span> <span class="token class-name">ActiveController</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token variable">$modelClass</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'app\models\User'</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token variable">$serializer</span> <span class="token operator">=</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'class'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'yii\rest\Serializer'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'collectionEnvelope'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'items'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>You may then get the following response for request <code v-pre>http://localhost/users</code>:</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token constant">HTTP</span><span class="token operator">/</span><span class="token number">1.1</span> <span class="token number">200</span> <span class="token constant">OK</span></span>
<span class="line">Date<span class="token punctuation">:</span> Sun<span class="token punctuation">,</span> <span class="token number">02</span> Mar <span class="token number">2014</span> <span class="token number">05</span><span class="token punctuation">:</span><span class="token number">31</span><span class="token punctuation">:</span><span class="token number">43</span> <span class="token constant">GMT</span></span>
<span class="line">Server<span class="token punctuation">:</span> Apache<span class="token operator">/</span><span class="token number">2.2</span><span class="token number">.26</span> <span class="token punctuation">(</span>Unix<span class="token punctuation">)</span> <span class="token constant">DAV</span><span class="token operator">/</span><span class="token number">2</span> <span class="token constant">PHP</span><span class="token operator">/</span><span class="token number">5.4</span><span class="token number">.20</span> mod_ssl<span class="token operator">/</span><span class="token number">2.2</span><span class="token number">.26</span> OpenSSL<span class="token operator">/</span><span class="token number">0.9</span><span class="token number">.8</span>y</span>
<span class="line"><span class="token constant">X</span><span class="token operator">-</span>Powered<span class="token operator">-</span>By<span class="token punctuation">:</span> <span class="token constant">PHP</span><span class="token operator">/</span><span class="token number">5.4</span><span class="token number">.20</span></span>
<span class="line"><span class="token constant">X</span><span class="token operator">-</span>Pagination<span class="token operator">-</span>Total<span class="token operator">-</span>Count<span class="token punctuation">:</span> <span class="token number">1000</span></span>
<span class="line"><span class="token constant">X</span><span class="token operator">-</span>Pagination<span class="token operator">-</span>Page<span class="token operator">-</span>Count<span class="token punctuation">:</span> <span class="token number">50</span></span>
<span class="line"><span class="token constant">X</span><span class="token operator">-</span>Pagination<span class="token operator">-</span>Current<span class="token operator">-</span>Page<span class="token punctuation">:</span> <span class="token number">1</span></span>
<span class="line"><span class="token constant">X</span><span class="token operator">-</span>Pagination<span class="token operator">-</span>Per<span class="token operator">-</span>Page<span class="token punctuation">:</span> <span class="token number">20</span></span>
<span class="line">Link<span class="token punctuation">:</span> <span class="token operator">&lt;</span>http<span class="token punctuation">:</span><span class="token comment">//localhost/users?page=1>; rel=self,</span></span>
<span class="line">      <span class="token operator">&lt;</span>http<span class="token punctuation">:</span><span class="token comment">//localhost/users?page=2>; rel=next,</span></span>
<span class="line">      <span class="token operator">&lt;</span>http<span class="token punctuation">:</span><span class="token comment">//localhost/users?page=50>; rel=last</span></span>
<span class="line">Transfer<span class="token operator">-</span>Encoding<span class="token punctuation">:</span> chunked</span>
<span class="line">Content<span class="token operator">-</span>Type<span class="token punctuation">:</span> application<span class="token operator">/</span>json<span class="token punctuation">;</span> charset<span class="token operator">=</span><span class="token constant">UTF</span><span class="token operator">-</span><span class="token number">8</span></span>
<span class="line"></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token string double-quoted-string">"items"</span><span class="token punctuation">:</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token punctuation">{</span></span>
<span class="line">            <span class="token string double-quoted-string">"id"</span><span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token operator">...</span></span>
<span class="line">        <span class="token punctuation">}</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">{</span></span>
<span class="line">            <span class="token string double-quoted-string">"id"</span><span class="token punctuation">:</span> <span class="token number">2</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token operator">...</span></span>
<span class="line">        <span class="token punctuation">}</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token operator">...</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string double-quoted-string">"_links"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token string double-quoted-string">"self"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token string double-quoted-string">"href"</span><span class="token punctuation">:</span> <span class="token string double-quoted-string">"http://localhost/users?page=1"</span></span>
<span class="line">        <span class="token punctuation">}</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string double-quoted-string">"next"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token string double-quoted-string">"href"</span><span class="token punctuation">:</span> <span class="token string double-quoted-string">"http://localhost/users?page=2"</span></span>
<span class="line">        <span class="token punctuation">}</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string double-quoted-string">"last"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token string double-quoted-string">"href"</span><span class="token punctuation">:</span> <span class="token string double-quoted-string">"http://localhost/users?page=50"</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string double-quoted-string">"_meta"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token string double-quoted-string">"totalCount"</span><span class="token punctuation">:</span> <span class="token number">1000</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string double-quoted-string">"pageCount"</span><span class="token punctuation">:</span> <span class="token number">50</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string double-quoted-string">"currentPage"</span><span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string double-quoted-string">"perPage"</span><span class="token punctuation">:</span> <span class="token number">20</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="json-输出控制" tabindex="-1"><a class="header-anchor" href="#json-输出控制"><span>JSON 输出控制</span></a></h3>
<p>The JSON response is generated by the [[yii\web\JsonResponseFormatter|JsonResponseFormatter]] class which will use the [[yii\helpers\Json|JSON helper]] internally. This formatter can be configured with different options like for example the [[yii\web\JsonResponseFormatter::$prettyPrint|$prettyPrint]] option, which is useful on development for better readable responses, or [[yii\web\JsonResponseFormatter::$encodeOptions|$encodeOptions]] to control the output of the JSON encoding.</p>
<p>The formatter can be configured in the [[yii\web\Response::formatters|formatters]] property of the <code v-pre>response</code> application component in the application <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide/concept-configurations.md" target="_blank" rel="noopener noreferrer">configuration</a> like the following:</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token string single-quoted-string">'response'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line">    <span class="token string single-quoted-string">'formatters'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token class-name class-name-fully-qualified static-context"><span class="token punctuation">\</span>yii<span class="token punctuation">\</span>web<span class="token punctuation">\</span>Response</span><span class="token operator">::</span><span class="token constant">FORMAT_JSON</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">            <span class="token string single-quoted-string">'class'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'yii\web\JsonResponseFormatter'</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token string single-quoted-string">'prettyPrint'</span> <span class="token operator">=></span> <span class="token constant">YII_DEBUG</span><span class="token punctuation">,</span> <span class="token comment">// use "pretty" output in debug mode</span></span>
<span class="line">            <span class="token string single-quoted-string">'encodeOptions'</span> <span class="token operator">=></span> <span class="token class-name">JSON_UNESCAPED_SLASHES</span> <span class="token operator">|</span> <span class="token class-name">JSON_UNESCAPED_UNICODE</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token comment">// ...</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>When returning data from a database using the <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide/db-dao.md" target="_blank" rel="noopener noreferrer">DAO</a> database layer all data will be represented as strings, which is not always the expected result especially numeric values should be represented as numbers in JSON. When using the ActiveRecord layer for retrieving data from the database, the values for numeric columns will be converted to integers when data is fetched from the database in [[yii\db\ActiveRecord::populateRecord()]].</p>
<blockquote>
<p>💖喜欢本文档的，欢迎点赞、收藏、留言或转发，谢谢支持！<br>
作者邮箱：zhuzixian520@126.com，github地址：<a href="https://github.com/zhuzixian520" target="_blank" rel="noopener noreferrer">github.com/zhuzixian520</a></p>
</blockquote>
</div></template>


